package com.xu.t1.middleware.threadallocation;

import com.xu.t1.middleware.Thread.ThreadCounterService;
import com.xu.t1.middleware.online.OnlineUserManager;
import com.xu.t1.model.ThreadAllocationContext;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;

import java.util.concurrent.ExecutorService;
import java.util.concurrent.ThreadPoolExecutor;

@Component
public class ThreadHandler2 implements ThreadAllocationHandler {

    @Autowired
    @Qualifier("writeExecutor")
    private ExecutorService executor;

    @Value("${app.server-id}")
    private String serverId;

    private ThreadAllocationHandler nextHandler;


    // 系统最大线程数
    private static final int MAX_THREADS = 20;

    @Autowired
    private ThreadCounterService threadCounterService;

    @Autowired
    private OnlineUserManager onlineUserManager;

    @Override
    public boolean handle(ThreadAllocationContext context) {


        context.setMaxThreads(MAX_THREADS);
        context.setServerMaxThreads(MAX_THREADS);

        // 获取系统在线人数
        int totalOnline = onlineUserManager.getOnlineTotal();
        context.setTotalOnlineUsers(totalOnline);

        // 获取节点在线人数
        int serverOnlineCount = onlineUserManager.getServerOnlineCount(serverId);
        context.setServerOnlineUsers(serverOnlineCount);

        // 获取系统线程使用数
        int totalUsedThreads = context.getTotalUsedThreads();

        // 获取节点使用线程数
        if (executor instanceof ThreadPoolExecutor) {
            int serverUsedThreads = ((ThreadPoolExecutor) executor).getActiveCount();
            context.setServerUsedThreads(serverUsedThreads);
        }

        // 根据节点在线人数比例和剩余线程比例，按权重计算当前节点可分配的线程数
        double onlineRatio = (double) serverOnlineCount / totalOnline;
        double threadRatio = (double) (context.getServerMaxThreads() - context.getServerUsedThreads()) / (context.getMaxThreads() - totalUsedThreads);

        double nodeWeight = context.getAlphaPeopleWeight() * onlineRatio + context.getBetaThreadWeight() * threadRatio;
        double allocatableThreadsDouble = nodeWeight * (context.getMaxThreads() - totalUsedThreads);
        int allocatableThreadsInt = (int) Math.floor(allocatableThreadsDouble);  // 向下取整
        context.setAllocatableThreads(allocatableThreadsInt);

        return nextHandler.handle(context);
    }

    @Override
    public ThreadAllocationHandler setNext(ThreadAllocationHandler nextHandler) {
        this.nextHandler = nextHandler;
        return nextHandler;
    }
}